package app.vendorportal.service;

import app.vendorportal.domain.passport.ResetPasswordInfomation;
import app.vendorportal.domain.vendor.Vendor;
import app.vendorportal.domain.vendor.VendorStatus;
import app.vendorportal.domain.vendor.VendorUser;
import app.vendorportal.email.TemplateMailSender;
import app.vendorportal.email.domain.EmailTemplateName;
import app.vendorportal.repository.passport.ResetPasswordInfomationRepository;
import app.vendorportal.repository.vendor.VendorRepository;
import app.vendorportal.repository.vendor.VendorUserRepository;
import core.framework.util.DateRangeUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.inject.Inject;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

@Service
public class PassportService {

    private VendorRepository vendorRepository;
    private VendorUserRepository vendorUserRepository;
    private ResetPasswordInfomationRepository resetPasswordInfomationRepository;
    private PasswordService passwordService;
    private TemplateMailSender templateMailSender;
    private String photoServerUrl;

    private static final int RESETEMAILACTIVETIME = 10;

    public boolean validateLoginInfo(String emailAddress, String password, VendorUser vendorUser) {
        String digestPassword = passwordService.digestPassword(password, emailAddress.toLowerCase());
        if ((null != vendorUser) && digestPassword.equals(vendorUser.getPassword()) && vendorUser.isActive()) {
            Vendor vendor = vendorRepository.getVendorByVendorNumber(vendorUser.getVendorNumber());
            if ((null != vendor) && VendorStatus.A.equals(vendor.getVendorStatus()) && vendor.getVendorPortalStatus()) {
                return true;
            }
        }
        return false;
    }

    @Transactional
    public void sendResetPasswordEmail(VendorUser vendorUser, String serverUrl) {
        StringBuilder url = new StringBuilder(50);
        String checkCode = UUID.randomUUID().toString();
        url.append(serverUrl).append("/passport/resetPasswordRedirect?accode=").append(checkCode);

        List<ResetPasswordInfomation> oriResetPasswordInfomationList = resetPasswordInfomationRepository.getActiveResetPasswordInfomationList(vendorUser.getUserId());
        for (int i = 0; i < oriResetPasswordInfomationList.size(); i++) {
            ResetPasswordInfomation oriResetPasswordInfomation = oriResetPasswordInfomationList.get(i);
            oriResetPasswordInfomation.setLinkActive(false);
            resetPasswordInfomationRepository.save(oriResetPasswordInfomation);
        }

        ResetPasswordInfomation resetPasswordInfomation = new ResetPasswordInfomation();
        buildNewResetPasswordInfomation(resetPasswordInfomation, vendorUser.getUserId(), checkCode);
        resetPasswordInfomationRepository.save(resetPasswordInfomation);

        Map<String, String> values = new HashMap<String, String>();
        values.put("resetUrl", url.toString());
        values.put("firstName", vendorUser.getFirstName());
        values.put("toAddress", vendorUser.getEmail());
        values.put("contextServerUrl", photoServerUrl);
        templateMailSender.send(EmailTemplateName.RESET_PASSWORD, values);
    }

    public void buildNewResetPasswordInfomation(ResetPasswordInfomation resetPasswordInfomation, int vendorUserId, String checkCode) {
        resetPasswordInfomation.setVendorUserId(vendorUserId);
        resetPasswordInfomation.setCheckCode(checkCode);
        resetPasswordInfomation.setLinkActive(true);
        resetPasswordInfomation.setSendMailTime(new Date());
    }

    @Transactional
    public VendorUser setNewPassword(String emailAddress, String password) {
        VendorUser vendorUser = vendorUserRepository.getVendorUserByEmail(emailAddress);
        vendorUser.setPassword(passwordService.digestPassword(password, vendorUser.getEmail().toLowerCase()));
        vendorUser.setFirstLogin(false);
        vendorUserRepository.update(vendorUser);
        return vendorUser;
    }

    public boolean validateResetPasswordDateTime(Date sendMailTime) {
        Date currentTime = new Date();
        if (DateRangeUtils.hoursBetween(sendMailTime, currentTime) < RESETEMAILACTIVETIME) {
            return true;
        }
        return false;
    }

    public boolean verifyPasswordComplexity(String password) {
        if (passwordService.verifyPassword(password) && verifyPasswordLength(password)) {
            return true;
        }
        return false;
    }

    public boolean verifyPasswordLength(String password) {
        return password.length() >= 8 && password.length() <= 10 ? true : false;
    }

    public VendorUser getVendorUserByUserId(int userId) {
        return vendorUserRepository.getVendorUserByUserId(userId);
    }

    public VendorUser getVendorUserByEmail(String emailAddress) {
        return vendorUserRepository.getVendorUserByEmail(emailAddress);
    }

    public ResetPasswordInfomation getPasswordInfomationByCheckCode(String checkCode) {
        return resetPasswordInfomationRepository.getResetPasswordInfomationByCheckCode(checkCode);
    }

    @Inject
    public void setVendorRepository(VendorRepository vendorDao) {
        this.vendorRepository = vendorDao;
    }

    @Inject
    public void setVendorUserRepository(VendorUserRepository vendorUserDao) {
        this.vendorUserRepository = vendorUserDao;
    }

    @Inject
    public void setPasswordService(PasswordService passwordService) {
        this.passwordService = passwordService;
    }

    @Inject
    public void setResetPasswordInfomationRepository(ResetPasswordInfomationRepository resetPasswordInfomationDao) {
        this.resetPasswordInfomationRepository = resetPasswordInfomationDao;
    }

    @Inject
    public void setTemplateMailSender(TemplateMailSender templateMailSender) {
        this.templateMailSender = templateMailSender;
    }

    @Inject
    public void setPhotoServerUrl(@Value("${photo.server.url}") String photoServerUrl) {
        this.photoServerUrl = photoServerUrl;
    }

}
